home *** CD-ROM | disk | FTP | other *** search
- //: C25:PaperScissorsRock.cpp
- // From Thinking in C++, 2nd Edition
- // Available at http://www.BruceEckel.com
- // (c) Bruce Eckel 1999
- // Copyright notice in Copyright.txt
- // Demonstration of multiple dispatching
- #include "../purge.h"
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <cstdlib>
- #include <ctime>
- using namespace std;
-
- class Paper;
- class Scissors;
- class Rock;
-
- enum Outcome { win, lose, draw };
-
- ostream&
- operator<<(ostream& os, const Outcome out) {
- switch(out) {
- default:
- case win: return os << "win";
- case lose: return os << "lose";
- case draw: return os << "draw";
- }
- }
-
- class Item {
- public:
- virtual Outcome compete(const Item*) = 0;
- virtual Outcome eval(const Paper*) const = 0;
- virtual Outcome eval(const Scissors*) const= 0;
- virtual Outcome eval(const Rock*) const = 0;
- virtual ostream& print(ostream& os) const = 0;
- virtual ~Item() {}
- friend ostream&
- operator<<(ostream& os, const Item* it) {
- return it->print(os);
- }
- };
-
- class Paper : public Item {
- public:
- Outcome compete(const Item* it) {
- return it->eval(this);
- }
- Outcome eval(const Paper*) const {
- return draw;
- }
- Outcome eval(const Scissors*) const {
- return win;
- }
- Outcome eval(const Rock*) const {
- return lose;
- }
- ostream& print(ostream& os) const {
- return os << "Paper ";
- }
- };
-
- class Scissors : public Item {
- public:
- Outcome compete(const Item* it) {
- return it->eval(this);
- }
- Outcome eval(const Paper*) const {
- return lose;
- }
- Outcome eval(const Scissors*) const {
- return draw;
- }
- Outcome eval(const Rock*) const {
- return win;
- }
- ostream& print(ostream& os) const {
- return os << "Scissors";
- }
- };
-
- class Rock : public Item {
- public:
- Outcome compete(const Item* it) {
- return it->eval(this);
- }
- Outcome eval(const Paper*) const {
- return win;
- }
- Outcome eval(const Scissors*) const {
- return lose;
- }
- Outcome eval(const Rock*) const {
- return draw;
- }
- ostream& print(ostream& os) const {
- return os << "Rock ";
- }
- };
-
- struct ItemGen {
- ItemGen() { srand(time(0)); }
- Item* operator()() {
- switch(rand() % 3) {
- default:
- case 0:
- return new Scissors();
- case 1:
- return new Paper();
- case 2:
- return new Rock();
- }
- }
- };
-
- struct Compete {
- Outcome operator()(Item* a, Item* b) {
- cout << a << "\t" << b << "\t";
- return a->compete(b);
- }
- };
-
- int main() {
- const int sz = 20;
- vector<Item*> v(sz*2);
- generate(v.begin(), v.end(), ItemGen());
- transform(v.begin(), v.begin() + sz,
- v.begin() + sz,
- ostream_iterator<Outcome>(cout, "\n"),
- Compete());
- purge(v);
- } ///:~
-